module demo (
    //未标明类型，默认为wire
    //未标明位宽，默认为1
    input           clk,            //时钟
    input           rst_n,          //复位
    input   [3:0]   i_data,
    input   [3:0]   q_data,
    input           ready_in,       //准备输入
    input   [1:0]   sel,            //状态判断
    
    output  [4:0]   out_data,
    output          ready_out       //准备输出     
);

    reg [3:0] i_data_reg;
    reg [3:0] q_data_reg;
    reg [3:0] out_data_reg;

    reg [3:0] cnt;

    //计数器
    always @(posedge clk or negedge rst_n) begin    //敏感列表，时钟上升沿或复位下降沿
        if(!rst_n)                                  //复位
            cnt<=4'b0;
        
        else if(cnt==4'd8)                          //cnt到达8时清零
            cnt<=4'b0;
        
        else 
            cnt<=cnt+1'b1;
    end

    //reg in
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            i_data_reg<=4'd0;
        else if(cnt==4'd4)
            i_data_reg<=4'd3;
        else if(ready_in)
            i_data_reg<=i_data;      //如果ready_in为1，把q_data的值给q_data_reg
    end
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            q_data_reg<=4'd0;
        else if(cnt==4'd4)
            q_data_reg<=4'd3;
        else if(ready_in)
            q_data_reg<=q_data;
    end  

//-------------------------------------写法1------------------------------------------//
/*
    //MUX
    always @(*) begin
        case (sel)
            2'b00:  out_data_reg = i_data_reg;
            2'b01:  out_data_reg = i_data_reg * q_data_reg;
            2'b10:  out_data_reg = i_data_reg & q_data_reg;
            2'b11:  out_data_reg = i_data_reg && q_data_reg;
            default:;
        endcase
    end

    assign out_data = out_data_reg;
    assign ready_out = ready_in;
*/

//-------------------------------------写法2------------------------------------------//

    //MUX
    assign out_data = (sel==2'b00) ?  i_data_reg : 
                      (sel==2'b01) ? (i_data_reg * q_data_reg) :
                      (sel==2'b10) ? (i_data_reg & q_data_reg) :    //按位与
                                     (i_data_reg && q_data_reg);    //逻辑与  1或0
    assign ready_out = ready_in;                                    //开始输出

    /*  这是一个用三目运算符实现的多路选择器，其功能和上面用case实现的完全一致。
        三目运算符：布尔表达式?表达式1:表达式2  
        运算过程：如果布尔表达式的值为 true ，则返回 表达式1 的值，否则返回 表达式2 的值
    */
endmodule